#include <iostream>
#include <unistd.h>
#include <string>
#include <vector>
#include <sys/wait.h>
#include <sys/types.h>
#include "mywork.hpp"
using namespace std;

enum errtype
{
    Useage_error = 1,
    argverror,
    Pipeerror
};

void useage()
{
    cout << "./poll X(你要创造的进程数量)" << endl;
}
class Channle
{
public:
    Channle(int wfd, string &name, pid_t sub_procese_id)
        : _wfd(wfd), _name(name), _sub_procese_id(sub_procese_id)
    {
    }
    ~Channle() = default;
    void Debug_print()
    {
        cout << _wfd << " " << _name << " " << _sub_procese_id << " " << endl;
    }
    void Close(){ close(_wfd);}
    int getwfd() { return _wfd; }
    string getname() { return _name; }
    pid_t getid() { return _sub_procese_id; }

private:
    int _wfd;
    string _name;
    pid_t _sub_procese_id;
};

class procese_pool
{
public:
    procese_pool(int sub_procese_num)
        : _sub_process_num(sub_procese_num)
    {
    }
    ~procese_pool()
    {
    }
    int Channle_size()
    {
        return _Channles.size();
    }
    int Create_Procese(work_t work)
    {
        vector<int>fds;
        for (int number = 0; number < _sub_process_num; number++)
        {
            int pipefd[2] = {0,0};//管道进程间通信
            int n = pipe(pipefd);
            if (n < 0)
                return Pipeerror;
            pid_t id = fork();
            if (id == 0)//子进程
            {
                if(!fds.size())
                {
                    for(auto&fd:fds)
                    {
                        close(fd);//依次关闭继承的父进程fd 这样后续执行自己的任务就不会冲突 
                        cout<<"close:"<<fd<<" ";
                    }
                }
                close(pipefd[1]);//关闭写入
                // 执行任务
                dup2(pipefd[0], 0);
                work();
                exit(0);
            }
            string cname = "channel: " + to_string(number);
            _Channles.push_back(Channle(pipefd[1], cname, id));
            close(pipefd[0]);//关闭读取
            fds.push_back(pipefd[1]);//保存父进程的写入fd 便于子进程依次关闭
        }
        return 0;
    }
    void Killallprocese()
    {
        for(auto& Channle:_Channles)
        {
            Channle.Close(); 
            
              pid=Channle.getid();
            pid_t rid=waitpid(pid,nullptr,0);   
            if(rid==pid)
            {
                cout<<"wait successful"<<pid<<"success";
            }
            cout<<"Channle:"<<Channle.getname()<<pid<<"quit";
        }
    }
    void Sendtaskcode(int index, uint32_t code)
    {
        cout << "Send:" << code << " to" <<_Channles[index].getname()<<" id: "<<_Channles[index].getid()  << endl;
        write(_Channles[index].getwfd(), &code, sizeof(code));
    }

    int NextChannel()
    {
       static int next = 0;
        int c = next;
        next++;
        next %= _Channles.size();
        return c;
    }
    void DebugPrint()
    {
        for (auto &channle : _Channles)
        {
            channle.Debug_print();
        }
    }

private:
    int _sub_process_num;
    vector<Channle> _Channles;
};

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        useage();                      
        return argverror;
    }
    
    srand((uint64_t)time(nullptr));
    // 进程vector管理
    procese_pool *pool = new procese_pool(sub_procese_num); // 创建进程池
    pool->Create_Procese(worker);

    while (true) // 控制子进程
    {
        int channle = pool->NextChannel();    // 选进程
        uint32_t mission = Nexttask();       // 选任务
        pool->Sendtaskcode(channle, mission); // 发任务
        sleep(1);
    }
    delete pool;
    return 0;
}